﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MvcApplication.Models;

namespace MvcApplication.Controllers
{
  class NorthwindAccessConsolidator {
    private NorthwindEntities db = new NorthwindEntities();

    public IEnumerable<Product> ListProducts() {
      return db.Products;
    }

    public Product GetProduct(int id) {
      IEnumerable<Product> data = db.Products.Where(e => e.ProductID == id).Select(e => e);
      return data.Count() > 0 ? data.Single() : null;
    }

    public void DeleteProduct(int id) {
      Product prod = GetProduct(id);
      if (prod != null) {
        IEnumerable<Order_Detail> ods = db.Order_Details.Where(e => e.ProductID == id).Select(e => e);
        foreach (Order_Detail od in ods) {
          db.Order_Details.DeleteObject(od);
        }
        db.Products.DeleteObject(prod);
        SaveChanges();
      }
    }

    public void StoreNewProduct(Product prod) {
      db.Products.AddObject(prod);
      SaveChanges();
    }

    public void SaveChanges() {
      db.SaveChanges();
    }

    public IEnumerable<string> GetAllSuppliers() {
      return db.Suppliers.Select(e => e.CompanyName);
    }

    public IEnumerable<string> GetAllCategories() {
      return db.Categories.Select(e => e.CategoryName);
    }

    public string GetSupplierName(Product prod) {
      return db.Suppliers.Where(e => e.SupplierID == prod.SupplierID).Select(e => e.CompanyName).Single();
    }

    public string GetCategoryName(Product prod) {
      return db.Categories.Where(e => e.CategoryID == prod.CategoryID).Select(e => e.CategoryName).Single();
    }

    public int GetSupplierID(string name) {
      return db.Suppliers.Where(e => e.CompanyName == name).Select(e => e.SupplierID).Single();
    }

    public int GetCategoryID(string name) {
      return db.Categories.Where(e => e.CategoryName == name).Select(e => e.CategoryID).Single();
    }
  }

  [HandleError(Order = 2)]
  public class ProductController : Controller
  {
    private NorthwindAccessConsolidator nwa = new NorthwindAccessConsolidator();

    // GET: /Product/
    public ActionResult Index()
    {
      return View(nwa.ListProducts());
    }

    // GET: /Product/Details/5
    // [HandleError(View = "NoSuchRecordError", ExceptionType = typeof(NoSuchRecordException))]
    public ActionResult Details(int id)
    {
      Product prod = nwa.GetProduct(id);
      if (prod == null) {
        Session["UsrMsg"] = "Відсутній продукт з ProductID = " + id;
        throw new NoSuchRecordException();

        return RedirectToAction("CustomError", new {
          message = "You requested an unknown product",
          detail = String.Format("No record for ID of {0}", id)
        });
      } else {
        ViewData["SupName"] = nwa.GetSupplierName(prod);
        ViewData["CatName"] = nwa.GetCategoryName(prod);
        return View(prod);
      }
    }

    public ActionResult CustomError(string message, string detail) {
      ViewData["ErrorMessage"] = message;
      ViewData["ErrorDetail"] = detail;
      return View();
    }

    public ActionResult JsonDetails(int id) {
      Product prod = nwa.GetProduct(id);
      if (prod == null) {
        throw new NoSuchRecordException();
      } else {
        return Json(new {
          ProductId = prod.ProductID,
          ProductName = prod.ProductName,
          SupplierID = prod.SupplierID,
          CategoryID = prod.CategoryID,
          UnitPrice = prod.UnitPrice,
          UnitsInStock = prod.UnitsInStock,
          UnitsOnOrder = prod.UnitsOnOrder,
          ReorderLevel = prod.ReorderLevel,
          Discontinued = prod.Discontinued
        }, JsonRequestBehavior.AllowGet);
      }
    }

    // GET: /Product/Create
    [Authorize]
    public ActionResult Create()
    {
      ViewData["suppliers"] = new SelectList(nwa.GetAllSuppliers());
      ViewData["categories"] = new SelectList(nwa.GetAllCategories());

      Product prod = new Product();
      ProductListWrapper wrap = new ProductListWrapper() {
        product = prod,
      };
      return View(wrap);
    } 

    // POST: /Product/Create
    [HttpPost]
    public ActionResult Create(ProductListWrapper pwrap)
    {
      try {
        if (!ModelState.IsValid) {
          ViewData["suppliers"] = new SelectList(nwa.GetAllSuppliers());
          ViewData["categories"] = new SelectList(nwa.GetAllCategories());
          return View(pwrap);
        }
        Product prod = pwrap.product;
        prod.SupplierID = nwa.GetSupplierID(pwrap.SelectedSupplier);
        prod.CategoryID = nwa.GetCategoryID(pwrap.SelectedCategory);
        nwa.StoreNewProduct(prod);
        return RedirectToAction("Index");
      } catch (Exception e) {
        Session["UsrMsg"] = "Помилка збереження продукту:";
        Session["ErrMsg"] = (e.InnerException != null) ? e.InnerException.Message : e.Message;
        throw;
      }
    }
        
    // GET: /Product/Edit/5
    [Authorize]
    public ActionResult Edit(int id)
    {
      Product prod = nwa.GetProduct(id);
      if (prod == null) {
        Session["UsrMsg"] = "Відсутній продукт з ProductID = " + id;
        throw new NoSuchRecordException();
      } else {
        ViewData["suppliers"] = new SelectList(nwa.GetAllSuppliers());
        ViewData["categories"] = new SelectList(nwa.GetAllCategories());

        ProductListWrapper wrap = new ProductListWrapper() {
          product = prod,
          SelectedSupplier = nwa.GetSupplierName(prod),
          SelectedCategory = nwa.GetCategoryName(prod)
        };
        return View(wrap);
      }
    }

    // POST: /Product/Edit/5
    [HttpPost]
    public ActionResult Edit(int id, ProductListWrapper pwrap)
    {
        try
        {
          if (!ModelState.IsValid) {
            ViewData["suppliers"] = new SelectList(nwa.GetAllSuppliers());
            ViewData["categories"] = new SelectList(nwa.GetAllCategories());
            return View(pwrap);
          }

          Product prod = nwa.GetProduct(id);
          ProductListWrapper wrapper = new ProductListWrapper() {
            product = prod
          };
          UpdateModel(wrapper);
          prod.SupplierID = nwa.GetSupplierID(wrapper.SelectedSupplier);
          prod.CategoryID = nwa.GetCategoryID(wrapper.SelectedCategory);
          nwa.SaveChanges();
          return RedirectToAction("Index");
        }
        catch (Exception e)
        {
          Session["UsrMsg"] = "Помилка збереження продукту:";
          Session["ErrMsg"] = (e.InnerException != null) ? e.InnerException.Message : e.Message;
          throw;
        }
    }

    // GET: /Product/Delete/5
    [Authorize]
    public ActionResult Delete(int id)
    {
      Product prod = nwa.GetProduct(id);
      ViewData["SupName"] = nwa.GetSupplierName(prod);
      ViewData["CatName"] = nwa.GetCategoryName(prod);
      return View(prod);
    }

    // POST: /Product/Delete/5
    [HttpPost]
    public ActionResult Delete(int id, FormCollection collection)
    {
        try
        {
          nwa.DeleteProduct(id);
          return RedirectToAction("Index");
        }
        catch (Exception e)
        {
          Session["UsrMsg"] = "Помилка вилучення продукту:";
          Session["ErrMsg"] = (e.InnerException != null) ? e.InnerException.Message : e.Message;
          throw;
        }
    }

    class NoSuchRecordException : Exception {
    }
  }
}
